package com.yh.ldzl.controller;

import com.rabbitmq.client.Channel;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.BasicService;
import com.yh.ldzl.domain.QcDefectRecord;
import com.yh.ldzl.domain.QcIqc;
import com.yh.ldzl.domain.QcIpqc;
import com.yh.ldzl.domain.QcOqc;
import com.yh.ldzl.domain.QcResult;
import com.yh.ldzl.service.IQcDefectRecordService;
import com.yh.ldzl.service.IQcResultService;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 检验单缺陷记录消息处理Controller
 *
 * @author yanghuai
 * @date 2025-07-07
 */
@RestController
@RequestMapping("qc/record")
public class RecordActionController extends BaseController {
    @Autowired
    private IQcDefectRecordService qcDefectRecordService;

    @Autowired
    private IQcResultService qcResultService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Resource
    private BasicService basicService;

    // 消息类型常量
    private static final String MESSAGE_TYPE_HEADER = "message_type";
    private static final String MESSAGE_TYPE_QC_IQC = "qc_iqc";
    private static final String MESSAGE_TYPE_QC_IPQC = "qc_ipqc";
    private static final String MESSAGE_TYPE_QC_RQC = "qc_rqc";
    private static final String MESSAGE_TYPE_QC_OQC = "qc_oqc";
    
    // 消息处理器映射表，用于注册不同类型消息的处理逻辑
    private final Map<String, MessageHandler<?>> messageHandlers = new HashMap<>();
    
    /**
     * 初始化消息处理器
     */
    @PostConstruct
    public void init() {
        // 注册QcIqc类型消息的处理器
        messageHandlers.put(MESSAGE_TYPE_QC_IQC, this::processQcIqcMessage);
        
        // 注册QcIpqc类型消息的处理器
        messageHandlers.put(MESSAGE_TYPE_QC_IPQC, this::processQcIpqcMessage);
        
        // 注册QcRqc类型消息的处理器
        messageHandlers.put(MESSAGE_TYPE_QC_RQC, this::processQcRqcMessage);
        
        // 注册QcOqc类型消息的处理器
        messageHandlers.put(MESSAGE_TYPE_QC_OQC, this::processQcOqcMessage);
    }

    /**
     * 自动编码
     */
    private String generateCode(Long type) {
        // 调用远程服务（消费模式，确保每次调用都会递增流水号）
        AjaxResult codeResult = basicService.automaticallyNumbersConsume(type);

        // 确保远程调用返回了结果对象
        if (codeResult == null) {
            throw new ServiceException(String.format("远程获取编码调用失败，返回结果为空，类型: %d", type));
        }

        // 根据该接口的特殊设计，编码直接存放在msg字段
        Object msg = codeResult.get(AjaxResult.MSG_TAG);
        Object code = codeResult.get(AjaxResult.CODE_TAG);
        System.out.println("编码是：" + code);
        // 确保编码内容不为空
        if (msg == null || msg.toString().isEmpty()) {
            throw new ServiceException(String.format("远程获取编码成功，但返回的编码为空，类型: %d, 返回信息: %s", type, msg));
        }

        // 从AjaxResult中正确取出msg部分作为编码
        return msg.toString();
    }
    /**
     * 查询检验单缺陷记录列表
     */
    @PostMapping("selectQcDefectRecordList")
    public TableDataInfo list(QcDefectRecord qcDefectRecord)
        {
            System.out.println("handler:"+qcDefectRecord);
        startPage();
        return getDataTable(qcDefectRecordService.selectQcDefectRecordList(qcDefectRecord));
    }

    /**
     * 新增保存检验单缺陷记录
     */
    @PostMapping("insertQcDefectRecord")
    public boolean insertQcDefectRecord(@RequestBody QcDefectRecord qcDefectRecord)
    {
        return qcDefectRecordService.insertQcDefectRecord(qcDefectRecord);
    }
    /**
     * 修改保存检验单缺陷记录
     */
    @PostMapping("updateQcDefectRecord")
    public boolean updateQcDefectRecord(@RequestBody QcDefectRecord qcDefectRecord)
    {
        return qcDefectRecordService.updateQcDefectRecord(qcDefectRecord);
    }
    /**
     * 批量删除检验单缺陷记录
     */

    @PostMapping("deleteQcDefectRecord")
    public boolean deleteQcDefectRecord( Long[] ids)
    {
        return qcDefectRecordService.deleteQcDefectRecordByRecordIds(ids);
    }
    /**
     * 删除检验单缺陷记录
     */
    @PostMapping("deleteQcDefectRecordByRecordId")
    public boolean deleteQcDefectRecordByRecordId(@RequestBody Long recordId)
        {
        return qcDefectRecordService.deleteQcDefectRecordByRecordId(recordId);
    }

    /**
     * REST API接口，手动获取队列消息并处理
     * @param messageType 消息类型，默认为qc_iqc，支持qc_iqc和qc_ipqc
     */
    @GetMapping("/receive")
    public AjaxResult manualReceiveMessage(@RequestParam(required = false, defaultValue = "qc_iqc") String messageType) {
        try {
            // 根据消息类型获取处理器
            MessageHandler<?> handler = messageHandlers.get(messageType);
            if (handler == null) {
                return AjaxResult.error("不支持的消息类型: " + messageType);
            }
            
            // 直接从队列获取消息
            Object message = rabbitTemplate.receiveAndConvert("myQueue");
            if (message == null) {
                return AjaxResult.error("没有接收到消息，队列可能为空");
            }
            
            System.out.println("手动接收到消息：" + message);
            System.out.println("消息类型：" + message.getClass().getName());
            
            // 尝试处理消息
            boolean result = handler.processMessage(message);
            
            if (result) {
                return AjaxResult.success("成功处理消息", message);
            } else {
                return AjaxResult.error("处理消息失败");
            }
        } catch (ClassCastException e) {
            return AjaxResult.error("消息类型不匹配: " + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("接收或处理消息失败: " + e.getMessage());
        }
    }
    
    

    /**
     * RabbitMQ消息监听器，自动监听队列消息
     */
    @RabbitListener(queues = "myQueue")
    public void processMessage(Message message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) {
        try {
            if (message == null) {
                System.out.println("监听器接收到空消息");
                channel.basicAck(tag, false);
                return;
            }
            
            System.out.println("监听器接收到消息：" + message);
            System.out.println("消息ID: " + message.getMessageProperties().getMessageId());
            
            // 获取消息类型
            String messageType = (String) message.getMessageProperties().getHeaders().getOrDefault(
                MESSAGE_TYPE_HEADER, MESSAGE_TYPE_QC_IQC); // 默认为QcIqc类型
            
            // 获取对应的处理器
            MessageHandler<?> handler = messageHandlers.get(messageType);
            if (handler == null) {
                System.out.println("不支持的消息类型: " + messageType);
                // 消息类型不支持，拒绝消息但不重新入队
                channel.basicReject(tag, false);
                return;
            }
            
            // 从消息中提取payload
            Object payload = extractPayloadFromMessage(message);
            if (payload == null) {
                System.out.println("无法从消息中提取payload");
                channel.basicReject(tag, false);
                return;
            }
            
            // 使用对应的处理器处理消息
            boolean result;
            try {
                result = handler.processMessage(payload);
            } catch (ClassCastException e) {
                System.out.println("消息类型不匹配: " + e.getMessage());
                // 消息类型不匹配，拒绝消息但不重新入队
                channel.basicReject(tag, false);
                return;
            }
            
            // 无论处理结果如何，确认消息已处理
            channel.basicAck(tag, false);
            
            System.out.println("消息处理完成，已确认: " + tag + ", 结果: " + (result ? "成功" : "失败"));
        } catch (Exception e) {
            try {
                // 处理失败，拒绝消息并重新入队
                System.out.println("处理消息异常，拒绝消息并重新入队: " + e.getMessage());
                channel.basicNack(tag, false, true);
            } catch (IOException ex) {
                System.out.println("消息拒绝失败: " + ex.getMessage());
            }
            e.printStackTrace();
        }
    }
    
    /**
     * 从Message对象中提取payload
     */
    private Object extractPayloadFromMessage(Message message) {
        try {
            // 使用RabbitTemplate的消息转换器来反序列化消息体
            Object payload = rabbitTemplate.getMessageConverter().fromMessage(message);
            System.out.println("提取的payload类型: " + (payload != null ? payload.getClass().getName() : "null"));
            System.out.println("提取的payload内容: " + payload);
            
            // 如果payload是Map类型，尝试转换为QcIqc对象
            if (payload instanceof java.util.Map) {
                System.out.println("payload是Map类型，尝试转换为QcIqc对象");
                // 这里可以添加Map到QcIqc的转换逻辑，如果需要的话
            }
            
            return payload;
        } catch (Exception e) {
            System.out.println("提取payload失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 消息处理器接口，定义消息处理的通用方法
     */
    @FunctionalInterface
    private interface MessageHandler<T> {
        boolean processMessage(Object message) throws ClassCastException;
    }
    
    /**
     * 处理QcIqc消息的方法
     */
    @Transactional
    public boolean processQcIqcMessage(Object message) throws ClassCastException {
        QcIqc qcIqc;
        
        // 如果message是Map类型，尝试转换为QcIqc对象
        if (message instanceof java.util.Map) {
            System.out.println("消息是Map类型，尝试转换为QcIqc对象");
            try {
                // 使用ObjectMapper进行转换
                com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
                qcIqc = objectMapper.convertValue(message, QcIqc.class);
                System.out.println("Map转换为QcIqc成功");
            } catch (Exception e) {
                System.out.println("Map转换为QcIqc失败: " + e.getMessage());
                throw new ClassCastException("无法将Map转换为QcIqc: " + e.getMessage());
            }
        } else {
            // 直接强制转换
            qcIqc = (QcIqc) message;
        }
        
        try {
            System.out.println("qcIqc.getIqcId():" + qcIqc.getIqcId());
            
            QcResult qcResult = new QcResult();
            
            // 调用远程服务
            System.out.println("开始调用远程编码服务，参数: 9L");
            String codeResult = generateCode(9L);
            
            // 完整打印返回结果，帮助诊断
            System.out.println("自动编码: " + codeResult);
            

            
            // 检查编码是否为空
            if (codeResult == null || codeResult.toString().isEmpty()) {
                // 尝试使用备用方案生成编码
                String fallbackCode = "QCR" + System.currentTimeMillis();
                System.out.println("远程编码为空，使用备用编码: " + fallbackCode);
                qcResult.setResultCode(fallbackCode);
            } else {
                qcResult.setResultCode(codeResult);
            }
            
            // 设置其他字段
            qcResult.setSourceDocId(qcIqc.getIqcId());
            qcResult.setSourceDocName(qcIqc.getIqcName());
            qcResult.setSourceDocCode(qcIqc.getIqcCode());
            qcResult.setSourceDocType(qcIqc.getSourceDocType());
            qcResult.setMaterialCode(qcIqc.getGoodsCode());
            qcResult.setMaterialName(qcIqc.getGoodsName());
            qcResult.setMaterialSfn(qcIqc.getStockSfn());
            qcResult.setUnit(qcIqc.getUnitName());
            qcResult.setCreateBy(qcIqc.getCreateBy());

            
            // 插入记录
            int insertResult = qcResultService.insertQcResult(qcResult);
            boolean success = insertResult > 0;
            
            System.out.println("处理结果：" + (success ? "成功" : "失败"));
            return success;
        } catch (Exception e) {
            System.out.println("处理QcIqc消息异常: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * 处理QcIpqc消息的方法
     */
    @Transactional
    public boolean processQcIpqcMessage(Object message) throws ClassCastException {
        QcIpqc qcIpqc;
        
        // 如果message是Map类型，尝试转换为QcIpqc对象
        if (message instanceof java.util.Map) {
            System.out.println("消息是Map类型，尝试转换为QcIpqc对象");
            try {
                // 使用ObjectMapper进行转换
                com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
                qcIpqc = objectMapper.convertValue(message, QcIpqc.class);
                System.out.println("Map转换为QcIpqc成功");
            } catch (Exception e) {
                System.out.println("Map转换为QcIpqc失败: " + e.getMessage());
                throw new ClassCastException("无法将Map转换为QcIpqc: " + e.getMessage());
            }
        } else {
            // 直接强制转换
            qcIpqc = (QcIpqc) message;
        }
        
        try {
            System.out.println("qcIpqc.getIpqcId():" + qcIpqc.getIpqcId());
            
            QcResult qcResult = new QcResult();

            // 调用远程服务生成结果单编码
            System.out.println("开始调用远程编码服务，参数: 8L");
            String codeResult = generateCode(8L);
            
            // 完整打印返回结果，帮助诊断
            System.out.println("远程服务完整响应: " + codeResult);
            

            
            // 检查编码是否为空
            if (codeResult == null || codeResult.toString().isEmpty()) {
                // 尝试使用备用方案生成编码
                String fallbackCode = "QCR" + System.currentTimeMillis();
                System.out.println("远程编码为空，使用备用编码: " + fallbackCode);
                qcResult.setResultCode(fallbackCode);
            } else {
                qcResult.setResultCode(codeResult);
            }
            
            // 设置其他字段
            qcResult.setSourceDocId(qcIpqc.getIpqcId());
            qcResult.setSourceDocName(qcIpqc.getIpqcName());
            qcResult.setSourceDocCode(qcIpqc.getIpqcCode());
            qcResult.setSourceDocType(qcIpqc.getSourceDocType());
            qcResult.setProductId(qcIpqc.getProductId());
            qcResult.setProductCode(qcIpqc.getProductCode());
            qcResult.setProductName(qcIpqc.getProductName());
            qcResult.setProductSfn(qcIpqc.getProductSfn());
            qcResult.setUnit(qcIpqc.getUnit());
            qcResult.setCreateBy(qcIpqc.getCreateBy());
            
            // 插入记录
            int insertResult = qcResultService.insertQcResult(qcResult);
            boolean success = insertResult > 0;
            
            System.out.println("处理过程检验单消息结果：" + (success ? "成功" : "失败"));
            return success;
        } catch (Exception e) {
            System.out.println("处理QcIpqc消息异常: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 处理QcRqc消息的方法
     */
    @Transactional
    public boolean processQcRqcMessage(Object message) throws ClassCastException {
        com.yh.ldzl.domain.QcRqc qcRqc;
        
        // 如果message是Map类型，尝试转换为QcRqc对象
        if (message instanceof java.util.Map) {
            System.out.println("消息是Map类型，尝试转换为QcRqc对象");
            try {
                // 使用ObjectMapper进行转换
                com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
                qcRqc = objectMapper.convertValue(message, com.yh.ldzl.domain.QcRqc.class);
                System.out.println("Map转换为QcRqc成功");
            } catch (Exception e) {
                System.out.println("Map转换为QcRqc失败: " + e.getMessage());
                throw new ClassCastException("无法将Map转换为QcRqc: " + e.getMessage());
            }
        } else {
            // 直接强制转换
            qcRqc = (com.yh.ldzl.domain.QcRqc) message;
        }
        
        try {
            System.out.println("qcRqc.getRqcId():" + qcRqc.getRqcId());
            
            QcResult qcResult = new QcResult();
            
            // 调用远程服务生成结果单编码
            System.out.println("开始调用远程编码服务，参数: 10L");
            String codeResult = generateCode(10L);
            
            // 完整打印返回结果，帮助诊断
            System.out.println("远程服务完整响应: " + codeResult);
            

            // 检查编码是否为空
            if (codeResult == null || codeResult.toString().isEmpty()) {
                // 尝试使用备用方案生成编码
                String fallbackCode = "QCR" + System.currentTimeMillis();
                System.out.println("远程编码为空，使用备用编码: " + fallbackCode);
                qcResult.setResultCode(fallbackCode);
            } else {
                qcResult.setResultCode(codeResult);
            }
            
            // 设置其他字段
            qcResult.setSourceDocId(qcRqc.getRqcId());
            qcResult.setSourceDocName(qcRqc.getRqcName());
            qcResult.setSourceDocCode(qcRqc.getRqcCode());
            qcResult.setSourceDocType(qcRqc.getSourceDocType());
            qcResult.setMaterialId(qcRqc.getMaterialId());
            qcResult.setMaterialCode(qcRqc.getMaterialCode());
            qcResult.setMaterialName(qcRqc.getMaterialName());
            qcResult.setMaterialSfn(qcRqc.getMaterialSfn());
            qcResult.setUnit(qcRqc.getUnit());
            qcResult.setCreateBy(qcRqc.getCreateBy());
            
            // 插入记录
            int insertResult = qcResultService.insertQcResult(qcResult);
            boolean success = insertResult > 0;
            
            System.out.println("处理退料检验单消息结果：" + (success ? "成功" : "失败"));
            return success;
        } catch (Exception e) {
            System.out.println("处理QcRqc消息异常: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 处理QcOqc消息的方法
     */
    @Transactional
    public boolean processQcOqcMessage(Object message) throws ClassCastException {
        QcOqc qcOqc;
        
        // 如果message是Map类型，尝试转换为QcOqc对象
        if (message instanceof java.util.Map) {
            System.out.println("消息是Map类型，尝试转换为QcOqc对象");
            try {
                // 使用ObjectMapper进行转换
                com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
                qcOqc = objectMapper.convertValue(message, QcOqc.class);
                System.out.println("Map转换为QcOqc成功");
            } catch (Exception e) {
                System.out.println("Map转换为QcOqc失败: " + e.getMessage());
                throw new ClassCastException("无法将Map转换为QcOqc: " + e.getMessage());
            }
        } else {
            // 直接强制转换
            qcOqc = (QcOqc) message;
        }
        
        try {
            System.out.println("qcOqc.getOqcId():" + qcOqc.getOqcId());
            
            QcResult qcResult = new QcResult();
            
            // 调用远程服务生成结果单编码
            System.out.println("开始调用远程编码服务，参数: 11L");
            String codeResult = generateCode(11L);
            
            // 完整打印返回结果，帮助诊断
            System.out.println("远程服务完整响应: " + codeResult);
            
            // 检查返回结构
            if (codeResult == null) {
                throw new ServiceException("远程编码服务调用失败，返回为null");
            }
            

            
            // 检查编码是否为空
            if (codeResult == null || codeResult.toString().isEmpty()) {
                // 尝试使用备用方案生成编码
                String fallbackCode = "QCR" + System.currentTimeMillis();
                System.out.println("远程编码为空，使用备用编码: " + fallbackCode);
                qcResult.setResultCode(fallbackCode);
            } else {
                qcResult.setResultCode(codeResult);
            }
            
            // 设置其他字段
            qcResult.setSourceDocId(qcOqc.getOqcId());
            qcResult.setSourceDocName(qcOqc.getOqcName());
            qcResult.setSourceDocCode(qcOqc.getOqcCode());
            qcResult.setSourceDocType(qcOqc.getSourceDocType());
            qcResult.setProductId(qcOqc.getProductId());
            qcResult.setProductCode(qcOqc.getProductCode());
            qcResult.setProductName(qcOqc.getProductName());
            qcResult.setProductSfn(qcOqc.getProductSfn());
            qcResult.setUnit(qcOqc.getUnit());
            qcResult.setCreateBy(qcOqc.getCreateBy());
            
            // 插入记录
            int insertResult = qcResultService.insertQcResult(qcResult);
            boolean success = insertResult > 0;
            
            System.out.println("处理出货检验单消息结果：" + (success ? "成功" : "失败"));
            return success;
        } catch (Exception e) {
            System.out.println("处理QcOqc消息异常: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }
}
